<!DOCTYPE html>

<html lang="en">

<head>
    <title>WebGL 2 Samples - texture_2d_array</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div id="info">WebGL 2 Samples - texture_2d_array</div>
    <p id="description">
        A texture animation using texture 2d array. The texture is also non-power-of-2. 
    </p>
    
    <!-- WebGL 2 shaders -->
    <script id="vs" type="x-shader/x-vertex">
        #version 300 es
        #define POSITION_LOCATION 0
        #define TEXCOORD_LOCATION 4
        
        precision highp float;
        precision highp int;

        uniform mat4 MVP;

        layout(location = POSITION_LOCATION) in vec2 position;
        layout(location = TEXCOORD_LOCATION) in vec2 texcoord;

        out vec2 v_st;

        void main()
        {
            v_st = texcoord;
            gl_Position = MVP * vec4(position, 0.0, 1.0);
        }
    </script>

    <script id="fs" type="x-shader/x-fragment">
        #version 300 es
        precision highp float;
        precision highp int;
        precision highp sampler2DArray;

        uniform sampler2DArray diffuse;
        uniform int layer;

        in vec2 v_st;

        out vec4 color;

        void main()
        {
            color = texture(diffuse, vec3(v_st, layer));
        }
    </script>

    <script src="utility.js"></script>
    <script>
    (function () {
        'use strict';

        var canvas = document.createElement('canvas');
        canvas.height = window.innerHeight;
        canvas.width = canvas.height * 960 / 540;
        document.body.appendChild(canvas);

        var gl = canvas.getContext( 'webgl2', { antialias: false } );
        var isWebGL2 = !!gl;
        if(!isWebGL2) {
            document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href="https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">How to get a WebGL 2 implementation</a>';
            return;
        }

        // -- Init program
        var program = createProgram(gl, getShaderSource('vs'), getShaderSource('fs'));
        var mvpLocation = gl.getUniformLocation(program, 'MVP');
        var diffuseLocation = gl.getUniformLocation(program, 'diffuse');
        var layerLocation = gl.getUniformLocation(program, 'layer');

        // -- Init buffers
        var positions = new Float32Array([
            -1.0, -1.0,
             1.0, -1.0,
             1.0,  1.0,
             1.0,  1.0,
            -1.0,  1.0,
            -1.0, -1.0
        ]);
        var vertexPosBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        var texCoords = new Float32Array([
            0.0, 1.0,
            1.0, 1.0,
            1.0, 0.0,
            1.0, 0.0,
            0.0, 0.0,
            0.0, 1.0
        ]);
        var vertexTexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        // -- Init VertexArray
        var vertexArray = gl.createVertexArray();
        gl.bindVertexArray(vertexArray);

        var vertexPosLocation = 0; // set with GLSL layout qualifier
        gl.enableVertexAttribArray(vertexPosLocation);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
        gl.vertexAttribPointer(vertexPosLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        var vertexTexLocation = 4; // set with GLSL layout qualifier
        gl.enableVertexAttribArray(vertexTexLocation);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
        gl.vertexAttribPointer(vertexTexLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        gl.bindVertexArray(null);
        
        var texture = gl.createTexture();
        loadImage('../assets/img/di-animation-array.jpg', function(image){
            var NUM_IMAGES = 3;
            var IMAGE_SIZE = {
                width: 960,
                height: 540
            };
            // use canvas to get the pixel data array of the image
            var canvas = document.createElement('canvas');
            canvas.width = IMAGE_SIZE.width;
            canvas.height = IMAGE_SIZE.height * NUM_IMAGES;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(image, 0, 0);
            var imageData = ctx.getImageData(0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height * NUM_IMAGES);
            var pixels = new Uint8Array(imageData.data.buffer);
            
            // -- Init Texture
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture);
            gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage3D(
                gl.TEXTURE_2D_ARRAY,
                0,
                gl.RGBA,
                IMAGE_SIZE.width,
                IMAGE_SIZE.height,
                NUM_IMAGES,
                0,
                gl.RGBA,
                gl.UNSIGNED_BYTE,
                pixels
            );
            
            gl.useProgram(program);
            gl.bindVertexArray(vertexArray);
            
            var matrix = new Float32Array([
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0
            ]);
            gl.uniformMatrix4fv(mvpLocation, false, matrix);
            gl.uniform1i(diffuseLocation, 0);
            
            var frame = 0;
            (function render() {
                // -- Render
                gl.clearColor(1.0, 1.0, 1.0, 1.0);
                gl.clear(gl.COLOR_BUFFER_BIT);
                gl.uniform1i(layerLocation, frame);
                
                frame = (frame + 1) % NUM_IMAGES;
                
                gl.drawArrays(gl.TRIANGLES, 0, 6);
                
                setTimeout( function(){
                    requestAnimationFrame(render);
                }, 200);
            })();
        });
        
        // If you have a long-running page, and need to delete WebGL resources, use:
        //
        // gl.deleteBuffer(vertexPosBuffer);
        // gl.deleteBuffer(vertexTexBuffer);
        // gl.deleteTexture(texture);
        // gl.deleteProgram(program);
        // gl.deleteVertexArray(vertexArray);
    })();
    </script>
    
    <div id="highlightedLines"  style="display: none">#L145-L160</div>
</body>

</html>
